
#include "hashtable.h"
#include "fileOperations.h"

//intialize the hash table 

void create_hash() {
	//printf("\ninsrtydccsdf\n");
	int i;
	for (i = 0; i < HASHSIZE; i++) {
		hashTable[i] = (ifd) malloc(sizeof(iFileDesc));
		hashTable[i]->next = NULL;
		strcpy(hashTable[i]->name, "\0");
		hashTable[i]->offset = 0;
	}
}

// find the key

unsigned int hashFunction(char *fName) {

	//key = alphabetically
	//printf("file name %s\n" , fName);
	if (fName[0] >= 48 && fName[0] <= 57) // 0 -9
		return fName[0] - 48;
	else if (fName[0] >= 65 && fName[0] <= 90) // A to Z
		return fName[0] - 55;
	else if (fName[0] >= 97 && fName[0] <= 122) // a to z
		return fName[0] - 61;
	else
		return 0;
}

//insert the files in hash table

void insertFile(char* name, long offset) {
	//printf("\n$$$$$$$$$$$$$$$$$$$$$$\n");
	ifd newFile;
	int key;

	//memory has been allocated to hashblock but not the list so allocate it here
	newFile = (ifd) malloc(sizeof(iFileDesc));
	//printf("\nname = %s\n" , name);
	key = hashFunction(name);

	//copy the data from fildescriptor to the hash file descriptor
	
	//printf("file name is %s\n" , name);

	strcpy(newFile->name, name);
	newFile->offset = offset;
	newFile->next = NULL;
	//printf("key = %d\n " , key);
	if (key == -1){}
//		printf("Invalid file");
	else {
		if (key < 62 && key >= 0) {
			if (hashTable[key]->name == NULL) {
				//printf("when no element\n");
				hashTable[key] = newFile;
			} else {
				//printf("when element\n");
				//newfile->next should point to prev one
				//newFile should be on KEY

				newFile->next = hashTable[key];
				hashTable[key] = newFile;
			}
		}
	}
	free(newFile);
}

void traverseFile() {
	//printf("\n****************** Traversing********************\n");
	ifd hashList;
	int i;

	hashList = (ifd) malloc(sizeof(iFileDesc) + 10);
	for (i = 0; i < HASHSIZE; i++) {
		hashList = hashTable[i];
		//printf("%d\t", i);
		//simple linklist approach
		while (hashList != NULL) {
			printf(" %s\t " , hashList->name);
			hashList = hashList->next;
		}
		printf("\n");
	}
	free(hashList);
}

int searchHashFile(char *fName, char* outputFileName) {
	int key=0, flag = 0, count = 0;
	char *pointLoc;
	ifd hashList;
	key = hashFunction(fName);
	char *address;
	FILE* updtPtr;
	FileDescriptor flDes;
	
	hashList = (ifd) malloc(sizeof(iFileDesc));
	sr searchList;
	searchList = (sr) malloc (sizeof(serRes));

	//printf(" hash table 1\n");
	//key is known so find the filename in that hashblock
	hashList = hashTable[key];
	//printf(" hash table 2\n");

	//printf("HASH IS coming here to search %s\n" , fName);
	//printf("HASH file name  %s\n" , hashList->name);
	
	while(hashList != NULL) {
		//printf("Hash File Name %s\n", hashList->name);
		if (hashList->name==NULL) {
					
			flag = 0;
			break;
		} 
		else {
			
			pointLoc = strstr(hashList->name, fName);
			
			if (pointLoc != NULL) {
				count++;
				flag = 1;
				//find the address for the offset we have in the hashtable
				if ((updtPtr = fopen(fileSystemName, "rb")) == NULL) {
//				printf("File could not be opened by Hashtable\n");
					
					return 1;
				} else {
					fseek(updtPtr, hashList->offset, SEEK_SET);
					fread(&flDes, sizeof(FileDescriptor), 1, updtPtr);
					address = (char *) malloc(sizeof(flDes.address) + 10);
					strcpy(address, flDes.address);
					//printf("\n Coming here after strcpy\n");
					fclose(updtPtr);
				}
				//add in resultRes linkedList
				searchList = addInSearch(searchList, hashList->name, address);
				//printf("%s \t " , hashList->ptfd->name); 
				hashList = hashList->next;
			}
 
			else
			hashList = hashList->next;
		}
	}
	
	if(searchList!=NULL)
		return searchAndWrite(searchList,outputFileName); //write into the file

	return 1;

}

sr addInSearch(sr searchList, char *name, char *address) {
	//adding all the searched names in a linkedlist so that can be added in a file later with address path
	//printf("*************** addin Search***************\n");
	sr temp, temp_node;

	temp = ((sr) malloc(sizeof(serRes)));
	strcpy(temp->name, name);
	strcpy(temp->address, address);
	temp->next = NULL;

	if (searchList == NULL)
		searchList = temp;
	else {
		temp_node = searchList;
		while (temp_node->next != NULL)
			temp_node = temp_node->next;

		temp_node->next = temp;
	}
	//printf("$$$$ search Name %s\n" , searchList->address);
	return(searchList);
}

//Requirement is to write the searched output in a file 

int searchAndWrite(sr searchList, char* outputFileName) {
	//printf("\n \n \n  ************Search and Write************ \n \n \n");
	FILE *myFile;
	sr serTemp;
	myFile = fopen(outputFileName, "w");
	serTemp = searchList;
	if (myFile != NULL) {
		//simple linklist approach---- Write in the file 
		while (serTemp != NULL) {
			// Name is same as address -- it should only be the file/dir name
			// the child of root node contains two slashes while it should contain single slash only

			fprintf(myFile, " %s- ", serTemp->name);
			fprintf(myFile, " %s\n ", serTemp->address);
			serTemp = serTemp->next;
		}
//		printf("\n");
		return 0;
	}
	else
		return 1;
//	else
//		printf("SearchError");
}

void deleteFile(char *fName, long offset) {
	int key, flag = 0;
	ifd hashList, prev;
	key = hashFunction(fName);

	//key is known so find the filename in that hashblock
	hashList = (ifd) malloc(sizeof(iFileDesc));
	hashList = hashTable[key];
	prev = hashList;
	
	while (hashList != NULL && (flag != 1)) {

		if (hashList->name == NULL) {
			flag = 0;
			break;
		} else {
			//first element of hash table
			if (strcmp(fName, hashTable[key]->name) == 0) {
				if (hashTable[key]->offset == offset) {
					flag = 1;
					free(hashList);
					hashTable[key] = hashList->next;
					hashList = hashTable[key];
				}
				else
					hashList = hashList->next;
			} else if (strcmp(fName, hashList->name) == 0) {//internal node
				prev->next = hashList->next;
				prev = hashList->next;
				if (hashTable[key]->offset == offset) {
					flag = 1;
					free(hashList);
					hashList = NULL;
				}

				hashList = hashList->next;
			} else {//move to next node
				prev = hashList;
				hashList = hashList->next;
			}
		}
	}


}
